package com.imut.oa.aspect;

import com.imut.oa.annotation.AutoFill;
import com.imut.oa.contant.AutoFillConstant;
import com.imut.oa.contant.OperationType;
import com.imut.oa.util.ThreadLoaclUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;

@Aspect
@Component
@Slf4j
public class AutoFillAspect {

     @Pointcut("execution(* com.imut.oa.mapper.*.*(..)) && @annotation(com.imut.oa.annotation.AutoFill)")
     public void autoFillPointCut() {}

     @Before("autoFillPointCut()")
     public void autoFill(JoinPoint joinPoint) {
          log.info("公共字段自动填充");

          // 获取方法签名和注解
          MethodSignature signature = (MethodSignature) joinPoint.getSignature();
          AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);
          OperationType[] operationTypes = autoFill.value();

          // 获取方法参数
          Object[] args = joinPoint.getArgs();
          if (args == null || args.length == 0) {
               return;
          }

          Object entity = args[0];
          LocalDateTime now = LocalDateTime.now();
          Long currentUserId = ThreadLoaclUtil.getCurrentId();

          try {
               // 处理每个指定的操作类型
               for (OperationType operationType : operationTypes) {
                    switch (operationType) {
                         case INSERT:
                              // 插入操作：填充创建和更新的时间及用户
                              invokeSetter(entity, AutoFillConstant.SET_CREATE_TIME, now);
                              invokeSetter(entity, AutoFillConstant.SET_CREATE_USER, currentUserId);
                              log.info("INSERT操作: 设置createTime={}, createUser={}", now, currentUserId);
                              // 继续执行UPDATE的填充逻辑，以便同时设置updateTime和updateUser
                         case UPDATE:
                              // 更新操作：只填充更新时间和用户
                              invokeSetter(entity, AutoFillConstant.SET_UPDATE_TIME, now);
                              invokeSetter(entity, AutoFillConstant.SET_UPDATE_USER, currentUserId);
                              log.info("UPDATE操作: 设置updateTime={}, updateUser={}", now, currentUserId);
                              break;
                         default:
                              log.warn("不支持的操作类型: {}", operationType);
                    }
               }
          } catch (Exception e) {
               log.error("自动填充公共字段失败", e);
          }
     }

     // 辅助方法：调用对象的setter方法
     private void invokeSetter(Object obj, String methodName, Object value) throws Exception {
          Method method = obj.getClass().getDeclaredMethod(methodName, value.getClass());
          method.setAccessible(true);
          method.invoke(obj, value);
     }
}